package com.github.permissiondog.cancanpandroid.repository.impl;

import android.util.Log;
import android.widget.Toast;

import com.github.permissiondog.cancanpandroid.MyApplication;
import com.github.permissiondog.cancanpandroid.model.ApplicationStatus;
import com.github.permissiondog.cancanpandroid.model.TableQuestion;
import com.github.permissiondog.cancanpandroid.model.TableTemplate;
import com.github.permissiondog.cancanpandroid.repository.TemplateRepository;
import com.github.permissiondog.cancanpandroid.repository.api.TemplateApiService;
import com.github.permissiondog.cancanpandroid.repository.api.response.ApplicationInfoResponse;
import com.github.permissiondog.cancanpandroid.repository.api.response.QuestionsResponse;
import com.github.permissiondog.cancanpandroid.repository.api.response.TemplateResponse;
import com.github.permissiondog.cancanpandroid.repository.api.response.TemplatesResponse;
import com.github.permissiondog.cancanpandroid.util.CallBack;
import com.github.permissiondog.cancanpandroid.util.NetUtil;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class TemplateRepositoryImpl implements TemplateRepository {
    private static TemplateRepository INSTANCE;
    public static synchronized TemplateRepository getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new TemplateRepositoryImpl();
        }
        return INSTANCE;
    }
    private final TemplateApiService templateApiService;
    private TemplateRepositoryImpl() {
        this.templateApiService = NetUtil.RETROFIT.create(TemplateApiService.class);
    }

    @Override
    public void getTemplateById(int templateId, CallBack<TableTemplate> template) {
        templateApiService.getTemplate(templateId).enqueue(new Callback<>() {
            @Override
            public void onResponse(Call<TemplateResponse> call, Response<TemplateResponse> response) {
                if (!response.isSuccessful() || response.body() == null) {
                    Toast.makeText(MyApplication.getInstance().getApplicationContext(), "网络错误", Toast.LENGTH_LONG).show();
                    return;
                }
                if (!response.body().isOk()) {
                    Toast.makeText(MyApplication.getInstance().getApplicationContext(), "获取模板信息失败", Toast.LENGTH_LONG).show();
                    return;
                }
                template.callback(response.body().getTemplate());
            }

            @Override
            public void onFailure(Call<TemplateResponse> call, Throwable t) {
                Log.w("request", "获取模板信息失败", t);
            }
        });
    }

    @Override
    public void getTemplates(CallBack<List<TableTemplate>> templates) {
        templateApiService.getTemplates().enqueue(new Callback<>() {
            @Override
            public void onResponse(Call<TemplatesResponse> call, Response<TemplatesResponse> response) {
                if (!response.isSuccessful() || response.body() == null) {
                    Toast.makeText(MyApplication.getInstance().getApplicationContext(), "网络错误", Toast.LENGTH_LONG).show();
                    return;
                }
                if (!response.body().isOk()) {
                    Toast.makeText(MyApplication.getInstance().getApplicationContext(), "获取模板列表失败", Toast.LENGTH_LONG).show();
                    return;
                }
                templates.callback(response.body().getTemplates().stream().collect(Collectors.toList()));
            }

            @Override
            public void onFailure(Call<TemplatesResponse> call, Throwable t) {
                Log.w("request", "获取模板列表失败", t);
            }
        });
    }

    @Override
    public void getSelectableTemplates(CallBack<List<TableTemplate>> selectableTemplates) {
        getTemplates(templates -> ApplicationRepositoryImpl.getInstance().getApplicantApplications(apps -> {
            CompletableFuture.runAsync(() -> {
                var appInfoList = apps.stream().parallel().map(app -> {
                            var future = new CompletableFuture<ApplicationInfoResponse>();
                            Log.d("future", "开始: " + app.getId());
                            ApplicationRepositoryImpl.getInstance().getApplicationInfo(app.getId(), r -> {
                                Log.d("future", "完成: " + r.getApplication().getId());
                                var ok = future.complete(r);
                                Log.d("future", "完成OK? " + ok);
                            });
                            Log.d("future", "等待: " + app.getId());
                            var temp = future.join();
                            Log.d("future", "完成: " + temp.getTemplate().getTableName());
                            return temp;
                        }).filter(app -> app.getStatus().equals(ApplicationStatus.APPROVED) || app.getStatus().equals(ApplicationStatus.PENDING))
                        .map(app -> app.getTemplate().getId()).collect(Collectors.toSet());

                Log.d("future", "全部完成");
                selectableTemplates.callback(templates.stream().filter(t -> !appInfoList.contains(t.getId())).collect(Collectors.toList()));
            });
        }));
    }

    @Override
    public void getTemplateQuestions(int templateId, CallBack<List<TableQuestion>> questions) {
        templateApiService.getTemplateQuestions(templateId).enqueue(new Callback<>() {
            @Override
            public void onResponse(Call<QuestionsResponse> call, Response<QuestionsResponse> response) {
                if (!response.isSuccessful() || response.body() == null) {
                    Toast.makeText(MyApplication.getInstance().getApplicationContext(), "网络错误", Toast.LENGTH_LONG).show();
                    return;
                }
                if (!response.body().isOk()) {
                    Toast.makeText(MyApplication.getInstance().getApplicationContext(), "获取问题列表失败", Toast.LENGTH_LONG).show();
                    return;
                }
                questions.callback(response.body().getQuestions());
            }

            @Override
            public void onFailure(Call<QuestionsResponse> call, Throwable t) {
                Log.w("request", "获取问题列表失败", t);
            }
        });
    }
}
